/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦，本文采用木兰宽松许可证第2版]
 * 
 * https://zhiqim.org/project/zhiqim_kit/zhiqim_git.htm
 *
 * ZhiqimGit is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.git.command;

import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;

import org.zhiqim.git.Git;
import org.zhiqim.git.GitCommand;
import org.zhiqim.git.GitWalker;
import org.zhiqim.git.objer.objectid.RevCommit;
import org.zhiqim.git.objer.objectid.RevCommitDateComparator;

import org.zhiqim.kernel.paging.PageBuilder;
import org.zhiqim.kernel.paging.PageResult;
import org.zhiqim.kernel.util.Asserts;
import org.zhiqim.kernel.util.Lists;

/**
 * 提交日志命令<br>
 * https://www.kernel.org/pub/software/scm/git/docs/git-log.html<br><br>
 *
 * @version v1.0.0 @author zouzhigang 2017-4-27 新建与整理
 */
public class LogCommand extends GitCommand<PageResult<RevCommit>>
{
    private static final RevCommitDateComparator DATE_SORT = new RevCommitDateComparator();
    
    private RevCommit start;
    private int pageNo;
    private int pageSize;
    
    public LogCommand(Git git)
    {
        super(git);
    }

    /******************************************************************************/
    //设置参数
    /******************************************************************************/
    
    public LogCommand setStart(RevCommit start)
    {
        this.start = start;
        return this;
    }
    
    public LogCommand setPageNo(int pageNo)
    {
        this.pageNo = pageNo;
        return this;
    }

    public LogCommand setPageSize(int pageSize)
    {
        this.pageSize = pageSize;
        return this;
    }
    
    /******************************************************************************/
    //检查&调用
    /******************************************************************************/
    
    protected void preprocess()
    {
        if (pageNo == 0)
            pageNo = 1;
        
        if (pageSize == 0)
            pageSize = 20;
        
        if (start == null)
        {
            try{start = git.resolve(HEAD, RevCommit.class);}catch (IOException e){throw Asserts.exception("读取HEAD提交时异常", e);}
        }
    }
    
    protected PageResult<RevCommit> execute() throws Exception
    {
        //1.设置查询队列
        LinkedList<RevCommit> queue = new LinkedList<>();
        queue.addLast(start);
        
        ArrayList<RevCommit> list = new ArrayList<>();
        
        GitWalker walker = new GitWalker(git);
        boolean hasNext = false;
        int pageStart = (pageNo - 1) * pageSize;
        int pageSeq = 0;
        
        if (pageSeq++ >= pageStart)
            list.add(start);
        
        //2.循环查找
        first:while (true)
        {
            RevCommit c = queue.pollFirst();
            if (c == null)
                break;
            
            if (!c.hasParents())
               continue;
            
            for (RevCommit p : c.getParents())
            {
                p = walker.parseCommit(p);
                if (!p.isParsed())
                    p.parseHeaders(walker);
                
                if (list.contains(p))
                    continue;
                
                if (list.size() >= pageSize)
                {
                    hasNext = true;
                    break first;
                }
                
                if (pageSeq++ >= pageStart)
                    list.add(p);
                
                queue.add(p);
            }
        }
        
        list = Lists.sortAndTrim(list, DATE_SORT);
        return PageBuilder.newResult(hasNext, pageNo, pageSize, list);
    }
}
